<!-- 菜单预览 -->
<template>
    <el-scrollbar class="vue-box">
        <!-- 数据 -->
        <div class="p-box">
            <!-- 提示 -->
            <el-alert v-if="state.isServerMenu" class="win-tips" type="info" show-icon>
                <template #title>
                    提示：当前菜单为后端加载模式，在指定菜单项 鼠标右键 即可弹出修改按钮。 
                    <el-link type="primary" @click="tips" style="vertical-align: top; font-size: 13px;">[ 详情 ]</el-link>
                </template>
            </el-alert>
            <el-alert v-else class="win-tips" type="info" show-icon>
                <template #title>
                    提示：当前菜单列表为前端定义模式 ( 请在 menu-list.js 文件中编辑菜单信息)，此处仅做预览。
                    <el-link type="primary" @click="tips" style="vertical-align: top; font-size: 13px;">[ 详情 ]</el-link>
                </template>
            </el-alert>
            <div class="c-title">所有菜单</div>
            <!-- 树插件 -->
            <el-tree
                v-if="state.treeList.length > 0"
                ref="tree"
                :data="state.treeList"
                node-key="id"
                :default-expand-all="true"
                :expand-on-click-node="false"
                :check-on-click-node="true"
                @node-contextmenu="showRightBox"
            >
                <template #default="s">
                    <div class="custom-tree-node" :class=" 'tree-node-' + (s.data.show ?? 'auth') ">
                        <!-- 图标 -->
                        <svg-icon class="menu-icon" :name="s.data.icon"></svg-icon>
                        <!-- 标题 -->
                        <span>{{ s.data.title }}&emsp;</span>
                        <!-- 菜单id -->
                        <span v-if="state.showId">[ {{ s.data.id }} ]&emsp;</span>
                        <!-- 显示级别 -->
                        <span v-if="state.showShow">[ {{ {yes: '永远显示', auth: '鉴权显示', no: '永远隐藏'}[s.data.show ?? 'auth'] }} ]&emsp;</span>
                        <!-- 排序 -->
                        <span v-if="state.showSort">( {{ s.data.sort }} )&emsp;</span>
                        <!-- 备注信息 -->
                        <span class="menu-info" v-if="state.showInfo && s.data.info">————&nbsp; {{ s.data.info }} </span>
                    </div>
                </template>
            </el-tree>
            <div style="height: 300px;"></div>
            
            <!-- 确定按钮 -->
            <div class="foot-div">
                <hr class="foot-hr">
                <div class="c-item">
                    <el-button type="primary" icon="el-icon-Plus" class="btn-13" @click="add({id: '-1'})" v-if="state.isServerMenu">添加顶级菜单</el-button> &emsp;
                    <span>显示：</span>
                    <el-checkbox v-model="state.showId" label="菜单id" />
                    <el-checkbox v-model="state.showShow" label="菜单可见性" />
                    <el-checkbox v-model="state.showSort" label="排序索引" v-if="state.isServerMenu" />
                    <el-checkbox v-model="state.showInfo" label="菜单介绍" />
                </div>
            </div>
        </div>

        <!-- 右键菜单 -->
        <com-right-box ref="right-box">
            <template #default="s">
                <li @click="s.close2(); update(s.row);"><el-icon><el-icon-Edit /></el-icon> 修改 </li>
                <li @click="s.close2(); add(s.row)"> <el-icon><el-icon-Plus /></el-icon> 添加子级 </li>
                <li @click="s.close2(); sortUpper(s.row)"> <el-icon><el-icon-Top /></el-icon> 升1 </li>
                <li @click="s.close2(); sortDrop(s.row)"> <el-icon><el-icon-Bottom /></el-icon> 降1 </li>
                <li @click="s.close2(); sortTop(s.row)"> <el-icon><el-icon-Upload /></el-icon> 置顶 </li>
                <li @click="s.close2(); del(s.row)"> <el-icon><el-icon-Delete /></el-icon> 删除 </li>
                <li @click="s.close2()"> <el-icon><el-icon-Minus /></el-icon> 取消 </li>
            </template>
        </com-right-box>
        
    </el-scrollbar>
</template>

<script setup name="menu-list">
import ComRightBox from './../../components/com-right-box'
import SvgIcon from "../../components/svg-icon";
import {useMenuList} from "../../router";
import {arrayToTree, defineMenu} from "../../router/router-util";
import {getCurrentInstance, onMounted, reactive} from "vue";
import {useSettingStore} from "../../store/setting";
const settingStore = useSettingStore();
const { proxy } = getCurrentInstance();

// -------------------- 数据 --------------------
const state = reactive({
    isServerMenu: settingStore.isServerMenu,  // 是否从后端加载菜单 
    dataList: [], // 平面数组
    treeList: [], // 树形数组 
    showId: false, // 是否显示：菜单id
    showShow: true, // 是否显示：展示规则
    showSort: false, // 是否显示：排序
    showInfo: true, // 是否显示：菜单介绍
})  
// 加载
onMounted(() => {
    f5();
})

// -------------------- 函数 --------------------
// 加载
const f5 = function () {
    // 后端模式
    if(state.isServerMenu) {
        console.log('------ 后端模式，加载菜单')
        sa.ajax('/SpMenu/getList', function(res){
            state.dataList = [...res.data];
            state.treeList = defineMenu(arrayToTree(res.data));
        });
    } else {
        // 前端模式
        console.log('------ 前端模式，加载菜单')
        sa.ajax2('/SpMenu/getList', function(){
            state.treeList = useMenuList();
        });
    }
}
defineExpose({f5})

// 展开右键菜单
const showRightBox = function ($event, data) {
    if(state.isServerMenu) {
        proxy.$refs['right-box'].show($event, data);
    } else {
        sa.msg('当前菜单列表为前端定义模式 ( 请在文件 menu-list.js 中编辑菜单信息)，此处仅做预览。 ');
    }
}

// 增加 
const add = function (data) {
    // 获取最高的排序值
    let maxSort = 0;
    for (const item of state.dataList) {
        if(maxSort < item.sort) {
            maxSort = item.sort;
        }
    }
    maxSort++;
    sa.showModel('添加一个菜单', import('./menu-add.vue'), {parentId: data.id, sort: maxSort});
}
// 修改
const update = function (data) {
    sa.showModel('修改菜单', import('./menu-add.vue'), { id: data.id });
};
// 删除
const del = function(data) {
    sa.confirmWarn(`是否删除菜单 [ ${data.title} ] ? 此操作不可撤销`, function(){
        sa.ajax('/SpMenu/delete', { id: data.id }, function(res){
            // sa.arrayDelete(state.dataList, data);
            sa.ok('删除成功');
            f5();
        })
    });
};

// 返回指定菜单id的所有子菜单
const getChildren = function (id) {
    const arr = [];
    for (const menu of state.dataList) {
        if(menu.parentId === id) {
            arr.push(menu);
        }
    }
    return arr;
}

// 升1 交换顺序 
const sortUpper = function(menu){
    // 判断是否已经第一了 
    const arr = getChildren(menu.parentId);
    const index = arr.indexOf(menu);
    if(index === 0 || index === -1){
        return sa.msg('已经最高了！');	// 已经是第一
    }
    // 获取信息
    const sort = menu.sort;
    const preMenu = arr[index - 1];	// 上一个
    const preSort = preMenu.sort;
    if(sort === preSort){
        return sa.msg('当前项排序索引与上一项相同，无法进行快捷排序，请手动修改排序索引值', {anim: 6, icon: 5});
    }
    
    // 开始交换
    let success = 0;
    sa.loading('正在交换排序...');
    const ajax1 = sa.ajax('/SpMenu/updateSort', {id: menu.id, value: preSort}, function(res){
        success++;
    }, {msg: false});
    const ajax2 = sa.ajax('/SpMenu/updateSort', {id: preMenu.id, value: sort}, function(res){
        success++;
    }, {msg: false});
    sa.axios.all([ajax1, ajax2]).finally(function(res) {
        if(success === 2) {
            sa.ok('升1成功');
            f5();
        }
    })
};

// 降1 交换顺序 
const sortDrop = function(menu){
    // 判断是否已经第一了 
    const arr = getChildren(menu.parentId);
    const index = arr.indexOf(menu);
    if(index === arr.length - 1 || index === -1){
        return sa.msg('已经最低了！');	// 已经是第一
    }
    // 获取信息
    const sort = menu.sort;
    const nextMenu = arr[index + 1];	// 上一个
    const nextSort = nextMenu.sort;
    if(sort === nextSort){
        return sa.msg('当前项排序索引与下一项相同，无法进行快捷排序，请手动修改排序索引值', {anim: 6, icon: 5});
    }

    // 开始交换
    let success = 0;
    sa.loading('正在交换排序...');
    const ajax1 = sa.ajax('/SpMenu/updateSort', {id: menu.id, value: nextSort}, function(res){
        success++;
    }, {msg: false});
    const ajax2 = sa.ajax('/SpMenu/updateSort', {id: nextMenu.id, value: sort}, function(res){
        success++;
    }, {msg: false});
    sa.axios.all([ajax1, ajax2]).finally(function(res) {
        if(success === 2) {
            sa.ok('降1成功');
            f5();
        }
    })
};

// 置顶 
const sortTop = function(menu){
    // 判断是否已经第一了 
    const arr = getChildren(menu.parentId);
    const index = arr.indexOf(menu);
    if(index === 0 || index === -1){
        return sa.msg('已经最高了！');	// 已经是第一
    }
    // 获取全局最小排序值
    let minSort = menu.sort;
    for (const item of state.dataList) {
        if(minSort > item.sort) {
            minSort = item.sort;
        }
    }
    // 开始置顶
    minSort--;
    sa.ajax('/SpMenu/updateSort', {id: menu.id, value: minSort}, function(){
        sa.ok('置顶成功');
        f5();
    }.bind(this))
};

// 菜单模式提示
const tips = function () {
    let str = "<p>当前菜单加载模式为：" + (state.isServerMenu ? '后端模式' : '前端模式') + "。</p>";
    str += "<p>- 后端模式：从后端加载菜单，可在项目部署后动态增删改；</p>"
    str += "<p>- 前端模式：从前端定义菜单，需要在项目打包前统一定义菜单；</p>"
    str += "<p>你可以从 setting.js 配置文件中配置菜单加载的模式。</p>"
    str = '<div class="tips-box--8456617756">' + str + '</div>';
    sa.alert(str, {title: '提示', isHtmlFragment: true});
}

</script>

<style scoped lang="scss">
.vue-box{
    .p-box{padding: 1em 1.5em;}

    /* 调整一下样式 */
    :deep(.el-tree) {background-color: #f5f7f8;}
    :deep(.el-tree-node) {padding: 0 !important;}
    :deep(.el-tree-node__content) {
        height: 30px; line-height: 32px; overflow: hidden;
        .custom-tree-node{height: 32px;}
        &:hover{
            background-color: #CFE8FC !important;
        }
    }
    :deep(.el-tree-node__label){width: 100%;}

    // 不同可见性的菜单不同颜色
    .tree-node-yes{color: green;}
    .tree-node-auth{color: #2D8CF0;}
    .tree-node-no{color: #999;}
    
    /* 图标 */
    .menu-icon{
        vertical-align: middle;
        position: relative;
        top: -1px;
        margin-right: 6px;
        //width: 20px;
    }
    .menu-info{color: #999;}
    
    // 底部复选框样式 
    .foot-div{position: absolute; bottom: 0px; width: calc(100% - 3em); line-height: 80px; background-color: #f5f7f8;}
    .foot-div{
        .foot-hr{height: 2px;}
        .c-item{padding-left: 6em;}
        :deep(.el-checkbox){vertical-align: middle; margin-right: 10px;}
    }
}
</style>
<style lang="scss">
.tips-box--8456617756{
    color: #666;
    p{
        line-height: 26px;
    }
}
</style>
